<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  <script>

    function myCall(fn, obj, ...args) {
      console.log('myCall()')

      // return this(...args)

      if (obj===undefined || obj===null) {
        // obj = window

        return fn(...args)
      }

      // 给obj添加一个临时方法, 方法对应的函数就是当前函数(也就是this)
      obj.tempFn = fn

      // 通过obj调用这个方法
      const result = obj.tempFn(...args)

      // 删除obj上的临时方法
      delete obj.tempFn

      // 返回方法执行的结果
      return result
    }

    function myApply(fn, obj, args) {
      console.log('myApply()')

      // return this(...args)

      if (obj===undefined || obj===null) {
        // obj = window

        return fn(...args)
      }

      // 给obj添加一个临时方法, 方法对应的函数就是当前函数(也就是this)
      obj.tempFn = fn

      // 通过obj调用这个方法
      const result = obj.tempFn(...args)

      // 删除obj上的临时方法
      delete obj.tempFn

      // 返回方法执行的结果
      return result
    }

    function myBind (fn, obj, ...args) {
      return function (...args2) {
        return myCall(fn, obj, ...args, ...args2)
      }
    }


    Function.prototype.call = function (obj, ...args) {
      console.log('call()')

      // return this(...args)

      if (obj===undefined || obj===null) {
        // obj = window

        return this(...args)
      }

      // 给obj添加一个临时方法, 方法对应的函数就是当前函数(也就是this)
      obj.tempFn = this

      // 通过obj调用这个方法
      const result = obj.tempFn(...args)

      // 删除obj上的临时方法
      delete obj.tempFn

      // 返回方法执行的结果
      return result
    }
  </script>
  
  <script>
   
   
    var m = 1

    function fn(a, b) {
      console.log(a, b, this.m, this)
      return a + b
    }

    const obj = {
      m: 2
    }

    // fn.call(obj, 3, 4) // 
    // fn.call(undefined, 3, 4)
    // fn.apply(obj, [5, 6])

    // myCall(fn, obj, 3, 4)
    // myCall(fn, undefined, 3, 4)

    // myApply(fn, obj, [3, 4])
    // myApply(fn, undefined, [3, 4])


    myBind(fn, obj)(2, 3)
    myBind(fn, obj, 4)(2, 3)
    myBind(fn, obj,         5)(2, 3)


  </script>
</body>
</html>